/**
 *  Copyright (c) Filipe Manana <fdmanana@gmail.com>
 *  All rights reserved.
 * 
 *  This file is part of jsdet.
 *
 *  jsdet is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published
 *  by the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  jsdet is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with jsdet.  If not, see <http://www.gnu.org/licenses/>.
 *
 */


package jsdet.parsing;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import jsdet.exceptions.ParsingException;
import jsdet.parsing.antlr.JavaScriptLexer;
import jsdet.parsing.antlr.JavaScriptParser;

import org.antlr.runtime.ANTLRInputStream;
import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.RecognitionException;
import org.antlr.runtime.TokenRewriteStream;
import org.antlr.runtime.CommonTokenStream;

/**
 * 
 * @author Filipe Manana
 *
 */
public class Parser {

    private String fileName;
    private JavaScriptParser parser;
    private JavaScriptLexer lexer;


    public Parser(String fileName) throws FileNotFoundException, IOException {
        FileInputStream fis = new FileInputStream(fileName);
        init(fileName, fis);
    }


    public Parser(String fileName, InputStream inputStream) throws IOException {
        init(fileName, inputStream);
    }


    protected void init(String fileName, InputStream inputStream) throws IOException {
        this.fileName = fileName;

        ANTLRInputStream input = new ANTLRInputStream(inputStream);
        this.lexer = new JavaScriptLexer(input);

        TokenRewriteStream tokens = new TokenRewriteStream(this.lexer);
        // if last character of the input is not a newline or a semi-colon, the parser fails...
        tokens.insertAfter(tokens.getTokens().size() - 1, "\n");

        this.lexer = new JavaScriptLexer(new ANTLRStringStream(tokens.toString()));
        this.parser = new JavaScriptParser(new CommonTokenStream(lexer));
    }


    public void setDebug(boolean debug) {
        if ( debug ) {
            parser.setDebugMode();
        }
        else {
            parser.disableDebugMode();
        }
    }


    public void doParsing() throws ParsingException {

        try {
            parser.program();
        }
        catch(RecognitionException ex) {
            throw new ParsingException(ex.getMessage());
        }

        if (hasErrors()) {
            throw new ParsingException();
        }
    }


    public ParsingStats getParsingStats() {

        if (hasErrors()) {
            return null;
        }

        return parser.getParsingStats();
    }


    public String getFileName() {
        return fileName;
    }


    public boolean hasErrors() {
        return parser.hasErrors() || lexer.hasErrors();
    }


    public List<String> getErrors() {

        if (lexer.hasErrors()) {
            return lexer.getErrors();
        }
        else if (parser.hasErrors()) {
            return parser.getErrors();
        }

        return null;
    }
}
